package com.tuton.javanet.chapter04;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BlockEchoServer {

	private ServerSocketChannel serverSocketChannel;
	private int port = 8000;
	private ExecutorService executorService;
	private final int POOL_SIZE = 4;
	
	public BlockEchoServer() throws IOException {
		executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()
				* POOL_SIZE);
		serverSocketChannel = ServerSocketChannel.open();
		serverSocketChannel.socket().setReuseAddress(true);
		serverSocketChannel.socket().bind(new InetSocketAddress(port));
		System.out.println("Server was started....");
	
	}
	
	public static void main(String[] args) throws IOException {
		new BlockEchoServer().server();
	}

	private void server() throws IOException {
		try{
			while(true){
				SocketChannel socketChannel = serverSocketChannel.accept();
				executorService.execute(new Handler(socketChannel));
			}
		} catch(IOException e) {
			e.printStackTrace();
		}
	}

	private class Handler implements Runnable {

		SocketChannel socketChannel = null;
		
		public Handler(SocketChannel socketChannel) {
			this.socketChannel = socketChannel;
		}
		
		public void run() {
			Handle(socketChannel);
			
		}

		private void Handle(SocketChannel socketChannel2) {
			try{
				Socket socket = socketChannel.socket();
				BufferedReader br = getReader(socket);
				PrintWriter    pw = getWriter(socket);
				
				String msg = null;
				while((msg = br.readLine())!= null) {
					System.out.println(msg);
					pw.println(echo(msg));
				}
			} catch(IOException e) {
				e.printStackTrace();
			} finally {
				try{
					if(socketChannel != null) {
						socketChannel.close();
					}
				}catch(IOException e) {
					e.printStackTrace();
				}
			}
		}
		
		private BufferedReader getReader(Socket socket3) throws IOException {
			InputStream socketIn = socket3.getInputStream();
			return new BufferedReader(new InputStreamReader(socketIn));
		}
		
		private PrintWriter getWriter(Socket socket4) throws IOException {
			OutputStream socketOut = socket4.getOutputStream();
			return new PrintWriter(socketOut,true);
		}
	
		private String echo(String msg) {
			return "echo-" + msg;
		}
	}
	
	
}
